/*
 * Copyright (c) csii.com.cn 2016 zhaojin
 */

package com.csii.ssm.dto;

import com.csii.ssm.exception.AccessRuntimeException;
import com.csii.ssm.exception.AccessRuntimeExceptionDict;

import java.security.SecureRandom;
import java.util.LinkedList;
import java.util.Random;

/**
 * @author zhaojin 15398699939@163.com
 * @create 2016-08-13-12:08
 */

public class TokenList {

    private int delayTime;
    //linkedList集合中对多存储maxEntryNumber个Token对象
    private int maxEntryNumber;
    //token uniqueId的长度
    private int tokenLength = 6;
    //持有Token集合
    private LinkedList linkedList = new LinkedList();
    private static Random random = new SecureRandom();

    public TokenList(int maxEntryNumber, int delayTime, int tokenLength) {
        this.maxEntryNumber = maxEntryNumber;
        this.delayTime = delayTime;
        this.tokenLength = tokenLength;
    }

    public String toString() {
        return super.getClass().getName() + " :" + this.linkedList;
    }

    /**
     * 返回tokenLength长度的uniqueId
     * @return
     */
    public String getNextTokenId() {
        long l1 = random.nextLong();
        long l2 = (l1 >= 0L) ? l1 : -l1;
        StringBuffer localStringBuffer = new StringBuffer(Long.toString(l2, 36));
        while (localStringBuffer.length() < this.tokenLength)
            localStringBuffer.insert(0, '0');
        if (localStringBuffer.length() > this.tokenLength)
            return localStringBuffer.substring(localStringBuffer.length() - this.tokenLength);
        return localStringBuffer.toString();
    }

    public void add(Token paramToken) {
        synchronized (this.linkedList) {
            this.linkedList.addLast(paramToken);
            if (this.linkedList.size() > this.maxEntryNumber)
                this.linkedList.removeFirst();
        }
    }

    public Token get(String reqTokenUniqueId) {
        synchronized (this.linkedList) {
            for (int i = 0; i < this.linkedList.size(); ++i) {
                Token localToken = (Token) this.linkedList.get(i);
                if (!(localToken.getUniqueId().equals(reqTokenUniqueId)))
                    continue;
                long l = System.currentTimeMillis() - localToken.getAccessDate();
                if (l > this.delayTime * 1000) {
                    this.linkedList.remove(i);
                    throw new AccessRuntimeException(AccessRuntimeExceptionDict.ERROR_TOKEN_TIMEOUT);
                }
                this.linkedList.remove(i);
                return localToken;
            }
            return null;
        }
    }

    public Token look(String reqTokenUniqueId) {
        synchronized (this.linkedList) {
            for (int i = 0; i < this.linkedList.size(); ++i) {
                Token localToken = (Token) this.linkedList.get(i);
                if (!(localToken.getUniqueId().equals(reqTokenUniqueId)))
                    continue;
                long l = System.currentTimeMillis() - localToken.getAccessDate();
                if (l > this.delayTime * 1000) {
                    this.linkedList.remove(i);
                    throw new AccessRuntimeException(AccessRuntimeExceptionDict.ERROR_TOKEN_TIMEOUT);
                }
                return localToken;
            }
            return null;
        }
    }
}
